home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
os2
/
remin301.zip
/
REMIN300.ZIP
/
DOREM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-10
|
15KB
|
541 lines
/***************************************************************/
/* */
/* DOREM.C */
/* */
/* Contains routines for parsing reminders and evaluating */
/* triggers. Also contains routines for parsing OMIT */
/* commands. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992 by David F. Skoll. */
/* */
/***************************************************************/
#include <stdio.h>
#include "config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
PRIVATE int ParseTimeTrig ARGS ((ParsePtr s, TimeTrig *tim));
PRIVATE int ParseLocalOmit ARGS ((ParsePtr s, Trigger *t));
PRIVATE int ParseUntil ARGS ((ParsePtr s, Trigger *t));
/***************************************************************/
/* */
/* DoRem */
/* */
/* Do the REM command. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoRem(ParsePtr p)
#else
int DoRem(p)
ParsePtr p;
#endif
{
Trigger trig;
TimeTrig tim;
int r;
int jul;
/* Parse the trigger date and time */
if (r=ParseRem(p, &trig, &tim)) return r;
if (trig.typ == NO_TYPE) return E_EOLN;
if (trig.typ == SAT_TYPE) return DoSatRemind(&trig, &tim, p);
/* Calculate the trigger date */
jul = ComputeTrigger(JulianToday, &trig, &r);
if (r) return r;
/* Queue the reminder, if necessary */
#ifdef HAVE_QUEUED
if (jul == JulianToday &&
!(!IgnoreOnce &&
trig.once != NO_ONCE &&
FileAccessDate == JulianToday))
QueueReminder(p, trig.typ, &tim);
/* If we're in daemon mode, do nothing over here */
if (Daemon) return OK;
#endif
if (ShouldTriggerReminder(&trig, &tim, jul)) {
if (r=TriggerReminder(p, &trig, &tim, jul)) return r;
}
return OK;
}
/***************************************************************/
/* */
/* ParseRem */
/* */
/* Given a parse pointer, parse line and fill in a */
/* trigger structure. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
#else
int ParseRem(s, trig, tim)
ParsePtr s;
Trigger *trig;
TimeTrig *tim;
#endif
{
register int r;
Token tok;
trig->y = NO_YR;
trig->m = NO_MON;
trig->d = NO_DAY;
trig->wd = NO_WD;
trig->back = NO_BACK;
trig->delta = NO_DELTA;
trig->until = NO_UNTIL;
trig->rep = NO_REP;
trig->localomit = NO_WD;
trig->skip = NO_SKIP;
trig->once = NO_ONCE;
trig->typ = NO_TYPE;
tim->ttime = NO_TIME;
tim->delta = NO_DELTA;
tim->rep = NO_REP;
while(1) {
/* Read space-delimited string */
r = ParseToken(s, TokBuffer);
if (r) return r;
/* Figure out what we've got */
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_WkDay:
if (trig->wd & (1 << tok.val)) {
Eprint("Weekday specified twice");
return E_PARSE_ERR;
}
trig->wd |= (1 << tok.val);
break;
case T_Month:
if (trig->m != NO_MON) {
Eprint("Month specified twice");
return E_PARSE_ERR;
}
trig->m = tok.val;
break;
case T_Skip:
if (trig->skip != NO_SKIP) {
Eprint("Only use one of BEFORE, AFTER or SKIP");
return E_PARSE_ERR;
}
trig->skip = tok.val;
break;
case T_At:
r=ParseTimeTrig(s, tim);
if (r) return r;
break;
case T_RemType:
trig->typ = tok.val;
if (s->isnested) {
Eprint("Can't nest '%s' in expression", TokBuffer);
return E_PARSE_ERR;
}
return OK;
case T_Until:
r=ParseUntil(s, trig);
if (r) return r;
break;
case T_Year:
if (trig->y != NO_YR) {
Eprint("Year specified twice");
return E_PARSE_ERR;
}
trig->y = tok.val;
break;
case T_Day:
if (trig->d != NO_DAY) {
Eprint("Day of month specified twice");
return E_PARSE_ERR;
}
trig->d = tok.val;
break;
case T_Rep:
if (trig->rep != NO_REP) {
Eprint("Repeat value specified twice");
return E_PARSE_ERR;
}
trig->rep = tok.val;
break;
case T_Delta:
if (trig->delta != NO_DELTA) {
Eprint("Delta value specified twice");
return E_PARSE_ERR;
}
trig->delta = tok.val;
break;
case T_Back:
if (trig->back != NO_BACK) {
Eprint("Back value specified twice");
return E_PARSE_ERR;
}
trig->back = tok.val;
break;
case T_Once:
if (trig->once != NO_ONCE) {
Eprint("ONCE specified twice. (Hah.)");
return E_PARSE_ERR;
}
trig->once = ONCE_ONCE;
break;
case T_Omit:
r = ParseLocalOmit(s, trig);
if (r) return r;
break;
case T_Empty:
return OK;
default:
Eprint("Unknown token in REM command: %s", TokBuffer);
return E_PARSE_ERR;
}
}
}
/***************************************************************/
/* */
/* ParseTimeTrig - parse the AT part of a timed reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
#else
static int ParseTimeTrig(s, tim)
ParsePtr s;
TimeTrig *tim;
#endif
{
Token tok;
int r;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_Time:
tim->ttime = tok.val;
break;
case T_Delta:
tim->delta = (tok.val > 0) ? tok.val : -tok.val;
break;
case T_Rep:
tim->rep = tok.val;
break;
default:
if (tim->ttime == NO_TIME) {
Eprint("Expecting time after AT.");
return E_PARSE_ERR;
}
/* Save in global variable */
LastTriggerTime = tim->ttime;
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* ParseLocalOmit - parse the local OMIT portion of a */
/* reminder. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t)
#else
static int ParseLocalOmit(s, t)
ParsePtr s;
Trigger *t;
#endif
{
Token tok;
int r;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_WkDay:
t->localomit |= (1 << tok.val);
break;
default:
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* ParseUntil - parse the UNTIL portion of a reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseUntil(ParsePtr s, Trigger *t)
#else
static int ParseUntil(s, t)
ParsePtr s;
Trigger *t;
#endif
{
int y = NO_YR,
m = NO_MON,
d = NO_DAY;
Token tok;
int r;
if (t->until != NO_UNTIL) {
Eprint("Cannot specify UNTIL twice");
return E_PARSE_ERR;
}
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_Year:
if (y != NO_YR) {
Eprint("Year specified twice in UNTIL");
return E_PARSE_ERR;
}
y = tok.val;
break;
case T_Month:
if (m != NO_MON) {
Eprint("Month specified twice in UNTIL");
return E_PARSE_ERR;
}
m = tok.val;
break;
case T_Day:
if (d != NO_DAY) {
Eprint("Day specified twice in UNTIL");
return E_PARSE_ERR;
}
d = tok.val;
break;
default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("Incompletely specified UNTIL");
return E_PARSE_ERR;
}
t->until = Julian(y, m, d);
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* TriggerReminder */
/* */
/* Trigger the reminder if it's a RUN or MSG type. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
#else
int TriggerReminder(p, t, tim, jul)
ParsePtr p;
Trigger *t;
TimeTrig *tim;
int jul;
#endif
{
int r, y, m, d;
Trigger tempTrig;
TimeTrig tempTime;
Parser tempP;
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
if (t->typ == CAL_TYPE) return OK;
/* If we're in Daemon mode, do nothing over here... */
/* If it's a MSG-type reminder, issue the banner. */
if (t->typ == MSG_TYPE && !NumTriggered && !NextMode) {
CreateParser(Banner, &tempP);
tempP.allownested = 0;
tempTrig.typ = MSG_TYPE;
tempTime.ttime = SystemTime()/60;
if (!(r=DoSubst(&tempP, SubstBuffer, &tempTrig,
&tempTime, JulianToday, NORMAL_MODE)))
if (*SubstBuffer) printf("%s\n", SubstBuffer);
DestroyParser(&tempP);
}
/* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
format. */
if (NextMode) {
if (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) return r;
if (!*SubstBuffer) return OK;
FromJulian(jul, &y, &m, &d);
printf("%04d/%02d/%02d %s%s\n", y, m+1, d,
SimpleTime(tim->ttime, NULL),
SubstBuffer);
return OK;
}
/* Put the substituted string into the SubstBuffer */
if (r=DoSubst(p, SubstBuffer, t, tim, jul, NORMAL_MODE)) return r;
/* Go for it... */
if (t->typ == MSG_TYPE) printf("%s\n", SubstBuffer);
else system(SubstBuffer);
NumTriggered++;
return OK;
}
/***************************************************************/
/* */
/* ShouldTriggerReminder */
/* */
/* Return 1 if we should trigger a reminder, based on today's */
/* date and the trigger. Return 0 if reminder should not be */
/* triggered. */
/* */
/***************************************************************/
#ifdef __TURBOC__
#pragma argsused
#endif
#ifdef HAVE_PROTOS
PUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
#else
int ShouldTriggerReminder(t, tim, jul)
Trigger *t;
TimeTrig *tim;
int jul;
#endif
{
int r;
/* Handle the ONCE modifier in the reminder. */
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
return 0;
if (jul < JulianToday) return 0;
/* Don't trigger timed reminders if DontIssueAts is true, and if the
reminder is for today */
#ifdef HAVE_QUEUED
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
#endif
/* Don't trigger "old" timed reminders */
/*** REMOVED...
if (jul == JulianToday &&
tim->ttime != NO_TIME &&
tim->ttime < SystemTime() / 60) return 0;
*** ...UNTIL HERE */
/* If "infinite delta" option is chosen, always trigger future reminders */
if (InfiniteDelta || NextMode) return 1;
/* Move back by delta days, if any */
if (t->delta != NO_DELTA) {
if (t->delta < 0)
jul = jul + t->delta;
else {
r = t->delta;
while(r && jul > JulianToday) {
jul--;
if (!IsOmitted(jul, t->localomit)) r--;
}
}
}
/* Should we trigger the reminder? */
return (jul <= JulianToday);
}
/***************************************************************/
/* */
/* DoSatRemind */
/* */
/* Do the "satisfying..." remind calculation. */
/* */
/***************************************************************/
#ifdef __TURBOC__
#pragma argsused
#endif
#ifdef HAVE_PROTOS
PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
#else
int DoSatRemind(trig, tim, p)
Trigger *trig;
TimeTrig *tim;
ParsePtr p;
#endif
{
int iter, jul, r;
Value v;
char *s;
iter = 0;
jul = JulianToday;
while (iter++ < MaxSatIter) {
jul = ComputeTrigger(jul, trig, &r);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
s = p->pos;
r = EvaluateExpr(p, &v);
p->pos = s;
if (r) return r;
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
if (v.type == INT_TYPE && v.v.val) return OK;
if (v.type == STR_TYPE && *v.v.str) return OK;
jul++;
}
LastTrigValid = 0;
return OK;
}